/* eslint-disable @typescript-eslint/no-explicit-any */
// 一个通用的 debounce 工具函数
function debounce(func: (...args: any[]) => void, delay: number) {
  let timeoutId: number | null;
  return function (this: any, ...args: any[]) {
    if (timeoutId) {
      clearTimeout(timeoutId);
    }

    timeoutId = window.setTimeout(() => {
      func.apply(this, args);
    }, delay);
  };
}

// ⬇️ 这是我们的装饰器工厂函数
export function Debounce(delay: number) {
  // 1. 装饰器工厂返回一个真正的方法装饰器。这一步是同步的。
  return function (
    target: any,
    propertyKey: string,
    descriptor: PropertyDescriptor,
  ): PropertyDescriptor {
    // 2. 从属性描述符中获取原始方法。
    const originalMethod = descriptor.value;

    // 关键点：检查原始方法是否存在
    if (typeof originalMethod !== "function") {
      throw new Error("@Debounce decorator can only be applied to methods.");
    }

    // 3. 用一个新函数替换原始方法。这个替换过程是同步的。
    descriptor.value = debounce(originalMethod, delay);

    // 4. 同步返回修改后的属性描述符。
    return descriptor;
  };
}

// 如何使用
class ApiClient {
  @Debounce(500) // 应用装饰器
  async fetchData(query: string) {
    console.log(`Fetching data for: ${query}`);
    // 模拟一个异步 API 调用
    const response = await fetch(`https://api.example.com?q=${query}`);
    const data = await response.json();
    console.log("Data received:", data);
    return data;
  }
}

const client = new ApiClient();
console.log("Calling fetchData multiple times quickly...");

// 在 500ms 内，只有最后一次调用会真正执行
client.fetchData("first");
client.fetchData("second");
client.fetchData("third"); // 只有这个会触发 console.log 和 fetch

const g = <T extends string[] | []>(t: T) => t;

const h = g(["111", "222"]);
